#ifndef LCCSTUFFCOLLECTOR_DLCLUSTER

// presetting
#include<lcctoolbox_markset.hpp>

#ifdef _WIN32
// windows
#include<windows.h>
typedef HMODULE lccDLhandler;
#define lccDLload(filename) LoadLibrary(filename)
#define lccDLget(theHandler,funcname) GetProcAddress(theHandler,funcname)
#define lccDLfree(theHandler) FreeLibrary(theHandler)
#else
// linux
#include<dlfcn.h>
typedef void* lccDLhandler;
#define lccDLload(filename) dlopen(filename,RTLD_LAZY)
#define lccDLget(theHandler,funcname) dlsym(theHandler,funcname)
#define lccDLfree(theHandler) dlclose(theHandler)
#endif



namespace LccStuffCollector{




class dlCluster:private LccToolbox::GmarkSetAuto<lccDLhandler>{
public:
	~dlCluster();

	template<class T> bool add(T&& note,const char* filename);
	template<class T> void* getFunc(T&& note,const char* funcname);
	template<class T,class... Ts> size_t remove(T&& note,Ts&&... notes);
	size_t remove(){return 0;}
};


dlCluster::~dlCluster(){
	auto it=end();auto it_begin=begin();if(it_begin==it) return;
	// back to front
	do{lccDLfree((--it)->Pag);}while(it!=it_begin);
}


template<class T>
bool dlCluster::add(T&& note,const char* filename){
	if(!filename) return false;
	auto itPair=insert(std::forward<T>(note));
	if(!itPair.second) return false;

	itPair.first->Pag=lccDLload(filename);
	if(itPair.first->Pag) return true;

	erase(*itPair.first);
	return false;
}


template<class T>
void* dlCluster::getFunc(T&& note,const char* funcname){
	if(!funcname) return nullptr;
	auto it=find(std::forward<T>(note));
	if(it==end()) return nullptr;

	return lccDLget(it->Pag,funcname);
}


template<class T,class... Ts>
size_t dlCluster::remove(T&& note,Ts&&... notes){
	size_t count=0;
	auto it=find(std::forward<T>(note));
	if(it==end()) goto LEFT;
	
	lccDLfree(it->Pag);
	erase(*it);

	LEFT:
	return count+remove(std::forward<Ts>(notes)...);
}




}// namespace LccStuffCollector


#define LCCSTUFFCOLLECTOR_DLCLUSTER
#endif